package zack.gateway.assist.application;

import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import zack.gateway.assist.config.GatewayServiceProperties;
import zack.gateway.assist.domain.model.aggregates.ApplicationSystemRichInfo;
import zack.gateway.assist.domain.model.vo.ApplicationInterfaceVO;
import zack.gateway.assist.domain.model.vo.ApplicationSystemVO;
import zack.gateway.assist.domain.service.GatewayCenterService;
import zack.gateway.core.mapping.HttpCommandType;
import zack.gateway.core.mapping.HttpStatement;
import zack.gateway.core.session.Configuration;

import java.util.List;

/** 注册网关算力，拉取rpc服务信息并添加到网关
 * @author A1793
 */
public class GatewayApplication implements ApplicationContextAware,ApplicationListener<ContextClosedEvent> {
    private Logger logger = LoggerFactory.getLogger(GatewayApplication.class);


    private GatewayServiceProperties properties;
    private GatewayCenterService gatewayCenterService;
    private Configuration configuration;
    private Channel channel;

    public GatewayApplication(GatewayServiceProperties gatewayServiceProperties,
                              GatewayCenterService gatewayCenterService,
                              Configuration configuration,
                              Channel channel) {
        this.properties = gatewayServiceProperties;
        this.gatewayCenterService = gatewayCenterService;
        this.configuration = configuration;
        this.channel = channel;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 1. 注册网关服务；每一个用于转换 HTTP 协议泛化调用到 RPC 接口的网关都是一个算力，这些算力需要注册网关配置中心
       try{
           gatewayCenterService.doRegister(properties.getAddress(),
                   properties.getGroupId(),
                   properties.getGatewayId(),
                   properties.getGatewayName(),
                   properties.getGatewayAddress());
           addMapper("");
       }catch (Exception e){
           logger.error("网关服务启动失败，停止服务。{}", e.getMessage(), e);
           throw e;
       }

    }

    public void addMapper(String systemId) {
        ApplicationSystemRichInfo applicationSystemRichInfo = gatewayCenterService.pullApplicationSystemRichInfo(properties.getAddress(),
                properties.getGatewayId(),
                systemId);
        if(applicationSystemRichInfo == null){
            logger.warn("网关{}服务注册映射为空，请排查 gatewayCenterService.pullApplicationSystemRichInfo 是否检索到此网关算力需要拉取的配置数据。", systemId);
            return;
        }
        List<ApplicationSystemVO> applicationSystemVOS = applicationSystemRichInfo.getApplicationSystemVOS();
        for (ApplicationSystemVO applicationSystemVO : applicationSystemVOS) {
            List<ApplicationInterfaceVO> interfaceList = applicationSystemVO.getInterfaceList();
            if(interfaceList == null || interfaceList.isEmpty()){
                logger.warn("网关{}服务注册映射为空，请排查 gatewayCenterService.pullApplicationSystemRichInfo 是否检索到此网关算力需要拉取的配置数据。", systemId);
                return;
            }
            for (ApplicationInterfaceVO interfaceVO :interfaceList ) {
                //设置注册中心的接口信息
                configuration.registryConfig(applicationSystemVO.getSystemId(),
                        applicationSystemVO.getSystemRegistry(),
                        interfaceVO.getInterfaceId(),
                        interfaceVO.getInterfaceVersion());
                //设置方法调用的映射信息
                interfaceVO.getMethodList().forEach(interfaceMethodVO -> {
                    HttpStatement httpStatement = new HttpStatement(
                            applicationSystemVO.getSystemId(),
                            interfaceVO.getInterfaceId(),
                            interfaceMethodVO.getMethodId(),
                            interfaceMethodVO.getParameterType(),
                            interfaceMethodVO.getUri(),
                            HttpCommandType.valueOf(interfaceMethodVO.getHttpCommandType()),
                            interfaceMethodVO.isAuth()
                    );
                    configuration.addMapper(httpStatement);
                    logger.info("网关服务注册映射 系统：{} 接口：{} 方法：{}", applicationSystemVO.getSystemId(), interfaceVO.getInterfaceId(), interfaceMethodVO.getMethodId());
                });
            }
        }
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {

       try{
           if(channel.isActive()){
               logger.info("应用容器关闭，Api网关服务关闭。localAddress：{}", channel.localAddress());
               channel.close();
           }
       }catch(Exception e){
           logger.error("应用容器关闭，Api网关服务关闭失败", e);
       }
    }

    public void receiveMessage(Object message){
        addMapper(message.toString().substring(1,message.toString().length()-1));
    }

}
